import { Button, notification } from 'antd';
import { open } from '@tauri-apps/api/dialog';
import { v4 as uuidv4 } from 'uuid';
import type { ReactNode } from 'react';
import React, { useContext } from 'react';
import { invoke } from '@tauri-apps/api';
import type { FileEntry } from '@tauri-apps/api/fs';
import { readDir, readTextFile } from '@tauri-apps/api/fs';
import { extname, join, resolveResource } from '@tauri-apps/api/path';
import JSONBig from 'json-bigint';
import { generateTmpPathOrFile } from '../../util';
import { flattenTree } from '../../util/collection';
import { APP_TEXT, EXPORT_FILE } from '../../constants/default';
import { Handle } from '../../lib/handle';
import type { ILanhaiDataSchema, LanhaiDataSchema } from '../../lib/modules/interface';
import { FillContext } from '../app/Fill';
import { CONFIG_KEYS } from '../../constants/config';

export interface IExportProps {
  text?: string
  children?: ReactNode
}

export const useImport = () => {
  const {
    setLoading,
    setLoadingText,
    loading,
    config,
  } = useContext(FillContext);
  const handleImport = async (sourceFile: String = '') => {
    console.log(config);
    const source_file = sourceFile || await open({
      multiple: false,
      filters: [{
        name: 'zip',
        extensions: ['zip', 'chrtc'],
      }],
    });

    if (!source_file)
      return;

    if (!['zip', 'chrtc'].includes(await extname(await resolveResource(String(source_file))))) {
      notification.error({
        message: '文件格式校验失败',
      });
      return;
    }

    setLoading(true);

    try {
      setLoadingText('解密压缩包');
      const name = uuidv4();
      const target_file = await generateTmpPathOrFile(`${name}.zip`);
      // 解密
      console.log(`解密压缩包 - ${source_file} - ${target_file} 开始`);
      await invoke('decrypt_file', {
        sourceFile: source_file,
        targetFile: target_file,
      });
      console.log(`解密压缩包 - ${source_file} - ${target_file} 完成`);

      setLoadingText('解压压缩包');
      // 解压
      const unzip_path = await generateTmpPathOrFile(name);
      console.log(`解压压缩包 - ${target_file} - ${unzip_path} 开始`);
      await invoke('unzip', {
        sourceFile: target_file,
        targetPath: unzip_path,
      });
      console.log(`解压压缩包 - ${target_file} - ${unzip_path} 完成`);

      setLoadingText('解密文件');

      // 解密
      /**
       * step 1 读取文件列表
       * step 2 过滤文件
       * step 3 chunk 5 解密
       */
      const files = await readDir(unzip_path, {
        recursive: true,
      });
      console.log(files);
      const root_path = files[0].path;

      // 拉平集合
      const flatten_files = flattenTree<Omit<FileEntry, 'children'>>(files);
      console.log(flatten_files);
      // 过滤离线填报所需文件
      // const prefix = await join(...EXPORT_DATA);
      const prefix = await join(APP_TEXT);
      const regex = new RegExp(`${prefix}|\.json`);
      const filter_files = flatten_files.filter((item) => {
        return !item.type && !!regex.exec(item.path);
      });
      console.log(filter_files);
      // 并行解密待导入数据并写入
      const data: LanhaiDataSchema[] = (await Promise.all(filter_files.map(async (item) => {
        try {
          const content = await readTextFile(item.path);
          console.log(content);
          console.log(`解密内容 - ${item.path} - 开始`);
          const {
            value,
          }: {
            value: string
          } = await invoke('decrypt_content', {
            content,
          });

          // console.log(`解密内容 - ${item.path} - 完成`);
          // console.log(value);
          // console.log(`写入内容 - ${item.path} - 开始`);
          // await writeFile(item.path, value);
          // console.log(`写入内容 - ${item.path} - 完成`);

          return JSONBig.parse(value);
        }
        catch (error) {
          console.log(error);
        }
      }))).filter(item => !!item);
      console.log(data);
      const _data: ILanhaiDataSchema = new Map();
      data.forEach((item) => {
        // dataSource.json
        if (Array.isArray(item)) {
          _data.set(CONFIG_KEYS.DATA_SOURCE, item);
          return;
        }

        // Readme.json
        if (Object.prototype.hasOwnProperty.call(item, 'appType')) {
          _data.set(CONFIG_KEYS.README, item);
          return;
        }

        // 所有表字段转大写
        /**
         * 线上数据融合导出时表字段转小写
         * 线下业务开发时对接字典为大写, 所以这里把所有导入数据字段转大写
         */
        if (Array.isArray(item?.data)) {
          item.data = item.data.map((_item) => {
            const _tmp: any = {};
            Object.keys(_item).forEach((_key) => {
              _tmp[_key.toUpperCase()] = _item[_key];
            });

            return _tmp;
          });
        }

        _data.set(item.tableName, item);
      });

      // 并行处理待导入数据
      // await Promise.all(handle_files.map(async (item) => {
      //   try {
      //     const schema: LanhaiDataSchema = JSONBig.parse(await readTextFile(item?.path as string));

      //     console.log(schema);
      //     const module = FILL_TABLE_MAP[schema.tableName];
      //     console.log(module);
      //     return item;
      //   }
      //   catch (error) {
      //     console.log(error);
      //   }
      // }));
      // //
      setLoadingText('处理数据');

      const handle = new Handle();
      await handle.import(_data, await join(root_path, ...EXPORT_FILE), config);

      notification.success({
        message: '导入完成',
      });
    }
    catch (error) {
      console.log(error);
      notification.error({
        message: '导入失败',
      });
    }

    setLoading(false);
  };

  return {
    handleImport,
    loading,
  };
};

export const Import: React.FC<IExportProps> = ({ text = '导入', children }) => {
  const { handleImport, loading } = useImport();

  return (
    <>
      {
        children
          ? <div onClick={() => handleImport()}>{children}</div>
          : (
          <Button type="primary" loading={loading} onClick={() => handleImport()}>{text}</Button>
            )
      }
    </>
  );
};
